﻿using System.Linq;
using System.Runtime.CompilerServices;
using RayDen.Library.Core.Primitives;


namespace RayDen.RayEngine.Data {

    public class FrameBuffer {
        private float[] pixelData;
        public int ValuesPerPixel;
        private int pixelCount;
        private int width, height;

        public FrameBuffer(int w, int h) {
            this.ValuesPerPixel = 3;
            width = (w);
            height = (h);
            pixelCount = width * height * ValuesPerPixel;
            pixelData = new float[pixelCount];

            Clear();
        }


        public FrameBuffer(int w, int h, RgbSpectrum[] data)
        {
            this.ValuesPerPixel = 3;
            width = (w);
            height = (h);
            pixelCount = width * height * ValuesPerPixel;
            pixelData = new float[pixelCount];
            Clear();
            for (int i = 0; i < h; i++)
            {
                for (int j = 0; j < w; j++)
                {
                    var offs = j + i*w;
                    this.SetPixel(offs, ref data[offs]);
                }
            }
        }

        public void FromRgb(RgbSpectrum[] data)
        {
            for (int i = 0; i < height; i++)
            {
                for (int j = 0; j < width; j++)
                {
                    var offs = j + i * width;
                    this.SetPixel(offs, ref data[offs]);
                }
            }
        }

        public long NonZeroElements {
            get { return pixelData.Count(p => p > 0f); }
        }

        public void Clear() {
            for (int i = 0; i < pixelCount; ++i) {
                pixelData[i] = 0f;

            }
        }


        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void SetPixel(int index, ref  RgbSpectrum r) {
            pixelData[ValuesPerPixel * index]     = r.c1;
            pixelData[ValuesPerPixel * index + 1] = r.c2;
            pixelData[ValuesPerPixel * index + 2] = r.c3;
        }


        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void AddPixel(int index, ref  RgbSpectrum r)
        {
            pixelData[ValuesPerPixel * index] += r.c1;
            pixelData[ValuesPerPixel * index + 1] += r.c2;
            pixelData[ValuesPerPixel * index + 2] += r.c3;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void SetPixel(int index, float r, float g, float b) {
            pixelData[ValuesPerPixel * index] = r;
            pixelData[ValuesPerPixel * index + 1] = g;
            pixelData[ValuesPerPixel * index + 2] = b;
        }


        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public float[] GetPixelData() {
            return pixelData;
        }

    }
}
